home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr22 / dtkclk11.zip / WRITE.C < prev   
Text File  |  1993-05-05  |  5KB  |  188 lines

  1. /*
  2.  * Routines to write to the DTK clock/calendar board.
  3.  * (C) Copyright 1989 Richard B. Wales.  All Rights Reserved.
  4.  */
  5.  
  6. #include "clkdefs.h"
  7.  
  8.  
  9. /*
  10.  * WRITE_CLOCK
  11.  *    Writes a date/time stamp to the clock board.
  12.  *    An approximation (to within +/- 5 seconds) of the "seconds" value
  13.  *    is represented by offsetting the "day of the week" written to the
  14.  *    clock.  This offset can be retrieved later by comparing the real
  15.  *    day of the week corresponding to the clock date with the day of
  16.  *    the week claimed by the clock board.
  17.  */
  18. struct clockval *
  19. write_clock (struct clockval *cv)
  20. {    unsigned char clkdata[13];
  21.     int n, wkday;
  22.  
  23.     /* Make sure there is an input parameter. */
  24.     if (cv == NULL_CLOCK) return NULL_CLOCK;
  25.  
  26.     /*
  27.      * Do some simple sanity checking on the input.
  28.      */
  29.     if (cv->cv_month == 0 || cv->cv_day == 0 || cv->cv_hour >= 24
  30.         || cv->cv_minute >= 60 || cv->cv_second >= 60)
  31.         return NULL_CLOCK;
  32.  
  33.     /*
  34.      * The century must be correct for the
  35.      * range of years from 1980 through 2079.
  36.      */
  37.     if (cv->cv_century != ((cv->cv_year >= 80) ? 19 : 20))
  38.         return NULL_CLOCK;
  39.  
  40.     /*
  41.      * Verify the month number and the number of days in the month.
  42.      * Since 2000 is a leap year, the test for Feburary can assume
  43.      * that any year divisible by 4 is a leap year.
  44.      */
  45.     switch (cv->cv_month)
  46.     {
  47.         case 1: case 3: case 5: case 7:
  48.         case 8: case 10: case 12:
  49.             if (cv->cv_day > 31) return NULL_CLOCK;
  50.             break;
  51.         case 2:
  52.             if (cv->cv_day > ((cv->cv_year & 0x3) ? 28 : 29))
  53.                 return NULL_CLOCK;
  54.             break;
  55.         case 4: case 6: case 9: case 11:
  56.             if (cv->cv_day > 30) return NULL_CLOCK;
  57.             break;
  58.         default:
  59.             return NULL_CLOCK;
  60.     }
  61.  
  62.     /*
  63.      * Add five seconds to the time before writing it to the clock,
  64.      * so that the "tens of seconds" kludge with the day of the week
  65.      * (see below) will result in a value that is within five seconds
  66.      * either way of the actual time.
  67.      */
  68.     advance_time (cv, 5);
  69.  
  70.     /*
  71.      * Compute the day of the week.
  72.      */
  73.     wkday = day_of_the_week (cv);
  74.  
  75.     /*
  76.      * The 5832 chip contains a major design misfeature, in that the
  77.      * "seconds" information is always reset to zero when a new time
  78.      * is written to the clock, regardless of the actual "seconds"
  79.      * value being written.  In order to get around this problem to
  80.      * some degree, this program modifies the "day of the week" on
  81.      * the clock by adding a "tens of seconds" quantity to the day
  82.      * of the week before storing it in the clock.  This offset can
  83.      * be reconstructed later, when the clock value is read back, by
  84.      * comparing the clock's idea of the day of the week with the
  85.      * true day of the week.
  86.      */
  87.     wkday += cv->cv_second / 10;
  88.     wkday %= 7;
  89.     cv->cv_second = 0;
  90.  
  91.     /*
  92.      * Copy the input to the character array
  93.      * which will be used to set the clock.
  94.      */
  95.     clkdata[0]  = 0;        /* seconds -- always zero */
  96.     clkdata[1]  = 0;        /* seconds -- always zero */
  97.     clkdata[2]  = cv->cv_minute % 10;
  98.     clkdata[3]  = cv->cv_minute / 10;
  99.     clkdata[4]  = cv->cv_hour % 10;
  100.     clkdata[5]  = cv->cv_hour / 10;
  101.     clkdata[6]  = wkday;
  102.     clkdata[7]  = cv->cv_day % 10;
  103.     clkdata[8]  = cv->cv_day / 10;
  104.     clkdata[9]  = cv->cv_month % 10;
  105.     clkdata[10] = cv->cv_month / 10;
  106.     clkdata[11] = cv->cv_year % 10;
  107.     clkdata[12] = cv->cv_year / 10;
  108.     for (n = 0; n < 13; n++)
  109.         if (clkdata[n] > 9) return NULL_CLOCK;
  110.  
  111.     /*
  112.      * Set the extra bit which indicates 24-hour mode.
  113.      */
  114.     clkdata[5] |= 0x08;
  115.  
  116.     /*
  117.      * Determine whether the next February will have 29 days.
  118.      * This flag is set starting in March of the previous year;
  119.      * the 5832 clock chip automatically turns the flag off
  120.      * after February 29 has passed.
  121.      */
  122.     if (((cv->cv_year & 0x3) == 0 && cv->cv_month <= 2) ||
  123.         ((cv->cv_year & 0x3) == 3 && cv->cv_month >= 3))
  124.         clkdata[8] |= 0x40;
  125.  
  126.     /*
  127.      * Prepare to write data to the clock.
  128.      */
  129.     outportb (PPICTRL, PPI_WRITE);        /* ready to write to PPI */
  130.     outportb (CLKCTRL, 0);            /* clear clock control bits */
  131.  
  132.     /*
  133.      * Verify that the clock is actually there by writing an arbitrary
  134.      * value to the PPI's port B, and then trying to read it back.
  135.      * This test really only verifies that something resembling a PPI
  136.      * is active in the I/O port address space used by the DTK clock.
  137.      */
  138.     outportb (CLKADDR, 0x55);
  139.     if (inportb (CLKADDR) != 0x55) return NULL_CLOCK;
  140.  
  141.     /*
  142.      * Write the new clock value.
  143.      */
  144.     READY_TO_WRITE;
  145.     for (n = 0; n < 13; n++) WRITE_CLOCK (n);
  146.     DONE_WRITING;
  147.  
  148.     /*
  149.      * Indicate success by returning the input parameter value.
  150.      */
  151.     return cv;
  152. }
  153.  
  154.  
  155. /*
  156.  * TIME_TO_CLOCK
  157.  *    Converts DOS "date" and "time" structures into a unified
  158.  *    date/time stamp structure used in the rest of the program.
  159.  */
  160. void
  161. time_to_clock (struct date *da, struct time *ti,
  162.            struct clockval **cv)
  163. {    static struct clockval cval;
  164.  
  165.     /*
  166.      * Perform sanity checks on the input parameters.
  167.      */
  168.     if (cv != NULL_CLOCK_P) *cv = NULL_CLOCK;
  169.     if (da == NULL_DATE || ti == NULL_TIME || cv == NULL_CLOCK_P)
  170.         return;
  171.  
  172.     /*
  173.      * Transform the date and time into the clock structure.
  174.      */
  175.     cval.cv_century = da->da_year / 100;
  176.     cval.cv_year    = da->da_year % 100;
  177.     cval.cv_month   = da->da_mon;
  178.     cval.cv_day     = da->da_day;
  179.     cval.cv_hour    = ti->ti_hour;
  180.     cval.cv_minute  = ti->ti_min;
  181.     cval.cv_second  = ti->ti_sec;
  182.  
  183.     /*
  184.      * That's all.
  185.      */
  186.     *cv = &cval;
  187. }
  188.